import { app, desktopCapturer, ipcMain, screen } from 'electron'
import { RobotMsgType } from './types'
import log from '../../helper/log'
import grpc from '@grpc/grpc-js'
import { Init } from '../../init'
import { ServiceClient } from '@grpc/grpc-js/build/src/make-client'
import path, { resolve } from 'path'
import { execSync, spawn } from 'child_process'
import os from 'os'
import { is } from '@electron-toolkit/utils'

export class ShareWindow {
  static grpcClient: ServiceClient
  static grpcProcessor

  static createGrpcClient = async (GRPC_IP) => {
    try {
      log.log(`createGrpcClient: server ip : ${GRPC_IP}`)
      const { proto } = await import('./grpc/proto')
      const ClientConstructor = grpc.makeClientConstructor(
        (proto.robotOp as any).service,
        'robotOp',
        {}
      )
      this.grpcClient = new ClientConstructor(GRPC_IP, grpc.credentials.createInsecure())
    } catch (e) {
      log.info('createGrpcClient error')
      log.error(e)
    }
  }

  static async listenEvents(GRPC_IP) {
    ipcMain.handle('desktop', async () => {
      return await desktopCapturer
        .getSources({
          types: ['screen'],
          thumbnailSize: {
            width: 0,
            height: 0
          }
        })
        .then(async (sources) => {
          const size = await this.getScreenSize()
          if (sources.length >= 1) {
            return {
              sourceId: sources[0].id,
              ...size
            }
          } else {
            return {
              sourceId: -1,
              ...size
            }
          }
        })
    })

    ipcMain.addListener('robotOp', (_e, msg) => {
      try {
        this.opCompute(msg)
      } catch (e) {
        console.log(e)
      }
    })
    this.listenExit()
    this.startPyGrpc()
    await this.createGrpcClient(GRPC_IP)
    log.log('creraterGrpcClient exec finish')
  }

  static getScreenSize = async () => {
    const display = screen.getPrimaryDisplay()
    const { width: screenWidth, height: screenHeight } = display.size
    const width = screenWidth
    const height = screenHeight
    return {
      width,
      height,
      scaleFactor: display.scaleFactor
    }
  }

  static opCompute = async (msg: RobotMsgType) => {
    this.grpcClient.Opmouse(msg, function(err) {
      if (err) {
        console.log(err)
      }
    })
  }

  static startPyGrpc = () => {
    let py_path = ''
    if (is.dev){
      py_path =  path.resolve("resources/grpc-py.exe");
    }else{
      py_path =  path.join(process.resourcesPath, 'resources','grpc-py.exe');
    }
    log.log(`grpc-py path: ${py_path}`)
    this.grpcProcessor = spawn(py_path)
    this.grpcProcessor.stdout.on('data', (data) => {
      console.log(`stdout: ${data}`)
    })

    this.grpcProcessor.stderr.on('data', (data) => {
      console.error(`stderr: ${data}`)
    })

    this.grpcProcessor.on('close', (code) => {
      console.log(`child process exited with code ${code}`)
    })
  }

  static killSubProcess = () => {
    if (this.grpcProcessor) {
      try {
        if (os.platform() == 'darwin') {
          this.grpcProcessor.kill()
          // execSync(`kill -9 ${this.grpcProcessor.pid}`)
        } else {
          this.grpcProcessor.kill()
          // execSync(`taskkill /f /t /im "${this.grpcProcessor.pid}"`)
        }
      } catch (e) {
        log.error(`kill py process error: ${e}`)
      }
    }
    process.exit(0)
  }

  static listenExit = () => {
    const events = ['exit', 'SIGINT', 'SIGTERM']
    events.forEach((item) => {
      process.on(item, this.killSubProcess)
    })
    app.on('window-all-closed', () => {
      log.log('window-all-closed')
      this.killSubProcess()
    })
  }
}
